import logging
import re

from django.shortcuts import render, redirect
from django.views.generic import View
from django.conf import settings
from django import http
from django.core.urlresolvers import reverse
from django.contrib.auth import login, authenticate
from django_redis import get_redis_connection

from oauth.urtils import generate_access_token, check_access_token
from urtils.response_code import RETCODE
from QQLoginTool.QQtool import OAuthQQ
from oauth.models import OAuthQQUser
from meiduo.models import Users
from carts.utils import marge_carts_cookie_redis


# 构造日志输出器
logger = logging.getLogger('django')


class QQAuthUserView(View):
    """处理qq回调: oauth_callback"""
    def get(self, request):
        code = request.GET.get("code")
        if code is None:
            return http.HttpResponseForbidden("获取code失败")

        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 通过code获取access_token
            access_token = oauth.get_access_token(code)

            # 通过access_token获取openid
            openid = oauth.get_open_id(access_token)

        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError("获取oauth2.0失败")

        # 通过openid判断qq用户是不是绑定过美多的用户
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            """用户未绑定美多商城"""
            token_access_openid = generate_access_token(openid)
            contentx = {"access_token_openid": token_access_openid}
            return render(request, 'oauth_callback.html', contentx)

        else:
            """用户已经绑定美多商城"""
            # 实现状态保持
            # 手动登录用户时，必须在调用login（）之前使用authenticate（）成功认证用户。
            try:
                login(request, oauth_user.user)
            except:
                pass
            # login(request, oauth_user)

            # 重定向到首页
            # 重定向 获取　state
            next = request.GET.get("state")
            response = redirect(next)
            # 将用户名写入到cookie
            response.set_cookie("username", oauth_user.user.username, max_age=3600 * 24 * 15)

            return response
        pass

    def post(self, request):
        """实现绑定用户的逻辑"""
        mobile = request.POST.get("mobile")
        password = request.POST.get("password")
        sms_code_client = request.POST.get("sms_code")
        access_token_openid = request.POST.get("access_token_openid")

        # 判断数据是否为空
        if not all([mobile, password, sms_code_client, access_token_openid]):
            return http.HttpResponseForbidden("缺少必穿参数")

        # 判断手机号是否合格
        if not re.match(r"^1[3-9]\d{9}$", mobile):
            return http.HttpResponseForbidden("请输入正确的手机号")

        # 判断密码是否合格
        if not re.match(r"^[0-9a-zA-Z_-]{8,20}$", password):
            return http.HttpResponseForbidden("请输入8-20位密码")

        # 判断手机验证码
        redis_conn = get_redis_connection("verify_code")
        sms_code_server = redis_conn.get(mobile).decode()
        if sms_code_server is None:
            return render(request, "oauth_callback.html", {"sms_code_errmsg": "无效的验证码"})

        if sms_code_client != sms_code_server:
            return render(request, "oauth_callback.html", {"sms_code_errmsg": "验证码错误"})

        # 判断openid是否存在
        openid = check_access_token(access_token_openid)
        if openid is None:
            return render(request, "oauth_callback.html", {"openid_errmsg": "openid已失效"})

        # 使用手机号查看用户是否绑定
        try:
            # 已绑定
            user = Users.objects.get(mobile=mobile)
        except Users.DoesNotExist:
            # 未绑定
            user = Users.objects.create(username=mobile, password=password, mobile=mobile)
        else:
            # 如果已经绑定校验密码
            if not user.check_password(password):
                return render(request, "oauth_callback.html", {"account_errmsg": "帐号或者密码错误"})

        # 将绑定和未绑定的openid添加到数据库
        try:
            oauth_qq_user = OAuthQQUser.objects.create(user=user, openid=openid)
        except Exception as e:
            logger.error(e)
            return render(request, "oauth_callback.html", {"qq_login_errmsg": "qq登录失败"})

        # 实现状态保持
        # 手动登录用户时，必须在调用login（）之前使用authenticate（）成功认证用户。
        try:
            # user = authenticate(username=user.username, password=password)
            login(request, oauth_qq_user.user)
        except:
            pass

        # 重定向 获取　state
        next = request.GET.get("state")
        response = redirect(next)

        # 登录用户时写入到cookie 有效期15天
        response.set_cookie("username", user.username, max_age=3600 * 24 * 15)

        response = marge_carts_cookie_redis(request, response, user)
        # 响应结果
        return response


class QQAuthURLView(View):
    """提供QQ登录扫码页面"""
    def get(self, request):
        # 接收next
        next = request.GET.get('next')

        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI, state=next)

        # 生成QQ登录扫码链接地址
        login_url = oauth.get_qq_url()

        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})